package io.github.talelin.latticy.service.impl;

import cn.hutool.core.lang.Assert;
import io.github.talelin.latticy.bo.OrderDetailVO;
import io.github.talelin.latticy.bo.OrderItemVO;
import io.github.talelin.latticy.common.constant.WmsConstant;
import io.github.talelin.latticy.common.enumeration.OrderStatusEnum;
import io.github.talelin.latticy.common.util.SnowFlake;
import io.github.talelin.latticy.dto.pick.PickDown;
import io.github.talelin.latticy.model.PickingDO;
import io.github.talelin.latticy.mapper.PickingMapper;
import io.github.talelin.latticy.model.PickingDetailDO;
import io.github.talelin.latticy.model.UserDO;
import io.github.talelin.latticy.service.PickingDetailService;
import io.github.talelin.latticy.service.PickingService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.github.talelin.latticy.service.UserService;
import io.github.talelin.latticy.service.feign.OrderFeignService;
import io.github.talelin.latticy.vo.FindResultVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * <p>
 * 出库拣货 服务实现类
 * </p>
 *
 * @author generator@wulongbo
 * @since 2022-08-17
 */
@Service
public class PickingServiceImpl extends ServiceImpl<PickingMapper, PickingDO> implements PickingService {

    @Resource
    private OrderFeignService orderFeignService;

    @Resource
    private PickingDetailService pickingDetailService;

    @Resource
    private UserService userService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void pickDown(PickDown pickDown) {
        List<OrderDetailVO> orderDetailVOs = new ArrayList<>(pickDown.getOrderIds().size());

        for (Long orderId : pickDown.getOrderIds()) {
            FindResultVO<OrderDetailVO> resultVO = orderFeignService.findById(orderId);
            OrderDetailVO orderDetailVO = resultVO.getData();
            Assert.notNull(orderDetailVO, "18804");
            Assert.notNull(!Objects.equals(OrderStatusEnum.APPROVED.getOrderStatusDesc(), orderDetailVO.getStatus()), "18805");
            orderDetailVOs.add(orderDetailVO);
        }
        // 校验所选的订单是否都是同一个仓库的
        long count = orderDetailVOs.stream().map(OrderDetailVO::getCode).distinct().count();
        Assert.isFalse(count > 1, "18806");

        // 校验所选的订单是否都是一种操作类型
        long operationTypeCount = orderDetailVOs.stream().map(OrderDetailVO::getOperationType).distinct().count();
        Assert.isFalse(operationTypeCount > 1, "18808");

        List<UserDO> pickers = userService.getPicker(orderDetailVOs.get(0).getCode());
        // 校验拣货员是否正确
        Optional<UserDO> pickerInfo = pickers.stream().filter(picker -> {
            return Objects.equals(picker.getId(), pickDown.getPickerId());
        }).findAny();
        Assert.isTrue(pickerInfo.isPresent(), "18807");

        PickingDO pickingDO = new PickingDO();
        SnowFlake idWorker = new SnowFlake(0, 0);
        pickingDO.setPickingNo(WmsConstant.PICKING_NO_PREFIX + idWorker.nextId());
        pickingDO.setPickingBy(pickerInfo.get().getUsername());
        pickingDO.setOperationType(orderDetailVOs.get(0).getOperationType());
        pickingDO.setWarehouseCode(orderDetailVOs.get(0).getCode());
        save(pickingDO);

        List<PickingDetailDO> pickingDetailDOS = new ArrayList<>();
        for (OrderDetailVO order : orderDetailVOs) {
            String orderNo = String.valueOf(order.getOrderNo());
            for (OrderItemVO orderItem : order.getOrderItems()) {
                PickingDetailDO pickingDetailDO = new PickingDetailDO();
                pickingDetailDO.setPickingNo(pickingDO.getPickingNo());
                pickingDetailDO.setOrderNo(orderNo);
                pickingDetailDO.setChannel(order.getLogistics());
                pickingDetailDO.setSku(orderItem.getSku());
                pickingDetailDO.setSkuName(orderItem.getProductName());
                pickingDetailDO.setQty(Long.valueOf(orderItem.getProductNum()));
//                pickingDetailDO.setLocation();
                pickingDetailDOS.add(pickingDetailDO);
            }
        }
        pickingDetailService.saveBatch(pickingDetailDOS);
    }
}
